﻿using System;
using System.IO;
using System.Linq;
using System.Text;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YJKRevitDimension.SymbolTextSetting;
using YJKGeometryFuncs;

namespace YJKRevitDimension.PlaneSlopeDimension
{
	internal class SlopeDimesionOper
	{
		public static bool CreateFamilySymbol(Autodesk.Revit.DB.Document currentDoc, SlopeDimensionStruct slopeDimStruct, out FamilySymbol fs)
		{
			Family family = slopeDimStruct.Family;
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(family.Document.EditFamily(family));
			filteredElementCollector.OfClass(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_GenericAnnotation);
			if (filteredElementCollector.Count<Element>() <= 0)
			{
				fs = null;
				return false;
			}
			string str = "";
			foreach (Element element in filteredElementCollector)
			{
				FamilyInstance familyInstance = element as FamilyInstance;
				if (familyInstance != null)
				{
					Family family2 = familyInstance.Symbol.Family;
					Document document = family2.Document.EditFamily(family2);
					FilteredElementCollector filteredElementCollector2 = new FilteredElementCollector(document);
					filteredElementCollector2.OfClass(typeof(TextElement));
					if (filteredElementCollector2.Count<Element>() <= 0)
					{
						fs = null;
						return false;
					}
					using (Transaction transaction = new Transaction(document))
					{
						try
						{
							if ((int)transaction.Start("Create Family") != 1)
							{
								fs = null;
								return false;
							}
							foreach (Element element2 in filteredElementCollector2)
							{
								TextElement textElement = element2 as TextElement;
								if (textElement != null)
								{
									TextElementType symbol = textElement.Symbol;
									str = string.Concat(new object[]
									{
										slopeDimStruct.Font,
										"-",
										slopeDimStruct.TextHeight,
										"-",
										slopeDimStruct.TextWidth
									});
									symbol.get_Parameter(BuiltInParameter.TEXT_FONT).Set(slopeDimStruct.Font);
									symbol.get_Parameter(BuiltInParameter.TEXT_SIZE).Set(SlopeDimesionOper.MMToFeet(slopeDimStruct.TextHeight));
									symbol.get_Parameter(BuiltInParameter.TEXT_WIDTH_SCALE).Set(slopeDimStruct.TextWidth);
								}
							}
							transaction.Commit();
							if (!File.Exists(Ultility.GetUserTempDirectory() + str + ".rfa"))
							{
								document.SaveAs(Ultility.GetUserTempDirectory() + str + ".rfa");
							}
							break;
						}
						catch (Exception)
						{
							transaction.RollBack();
							break;
						}
					}
				}
			}
			string text = string.Concat(new object[]
			{
				family.Name,
				"-",
				slopeDimStruct.Font,
				"-",
				slopeDimStruct.TextHeight,
				"-",
				slopeDimStruct.TextWidth
			});
			Document document2 = family.Document.EditFamily(family);
			FamilySymbol familySymbol = null;
			FilteredElementCollector filteredElementCollector3 = new FilteredElementCollector(document2);
			filteredElementCollector3.OfClass(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_GenericAnnotation);
			if (filteredElementCollector3.Count<Element>() <= 0)
			{
				fs = null;
				return false;
			}
			using (Transaction transaction2 = new Transaction(document2))
			{
				try
				{
                    if ((int)transaction2.Start("Create Family") != 1)
					{
						fs = null;
						return false;
					}
					Family family3;
					if (document2.LoadFamily(Ultility.GetUserTempDirectory() + str + ".rfa", out family3))
					{
						familySymbol = (document2.GetElement(family3.GetFamilySymbolIds().First<ElementId>()) as FamilySymbol);
						foreach (Element element3 in filteredElementCollector3)
						{
							FamilyInstance familyInstance = element3 as FamilyInstance;
							if (familyInstance != null)
							{
								familyInstance.Symbol = (familySymbol.Duplicate(familyInstance.Symbol.Family.Name) as FamilySymbol);
								document2.Regenerate();
								Parameter parameter = familyInstance.Symbol.GetParameters("坡度值").First<Parameter>();
								try
								{
									FamilyParameter familyParameter;
									if (familyInstance.Symbol.Name.Contains("上"))
									{
										familyParameter = document2.FamilyManager.get_Parameter("坡度上");
									}
									else if (familyInstance.Symbol.Name.Contains("下"))
									{
										familyParameter = document2.FamilyManager.get_Parameter("坡度下");
									}
									else
									{
										familyParameter = document2.FamilyManager.get_Parameter("坡度上");
									}
									document2.FamilyManager.AssociateElementParameterToFamilyParameter(parameter, familyParameter);
								}
								catch (Exception)
								{
								}
							}
						}
					}
					transaction2.Commit();
					if (!File.Exists(Ultility.GetUserTempDirectory() + text + ".rfa"))
					{
						document2.SaveAs(Ultility.GetUserTempDirectory() + text + ".rfa");
					}
					if (File.Exists(Ultility.GetUserTempDirectory() + str + ".rfa"))
					{
						Ultility.DeleteFile(Ultility.GetUserTempDirectory() + str + ".rfa");
					}
				}
				catch (Exception)
				{
					transaction2.RollBack();
					if (File.Exists(Ultility.GetUserTempDirectory() + str + ".rfa"))
					{
						Ultility.DeleteFile(Ultility.GetUserTempDirectory() + str + ".rfa");
					}
				}
			}
			Family family4;
			if (!Ultility.IsExistFamily(currentDoc, text, out family4))
			{
				using (Transaction transaction3 = new Transaction(currentDoc))
				{
					try
					{
                        if ((int)transaction3.Start("LoadFamilySymbol") != 1)
						{
							fs = null;
							return false;
						}
                        currentDoc.LoadFamily(Ultility.GetUserTempDirectory() + text + ".rfa", out family4);
						if (!SlopeDimesionOper.GetFamilySymbol(family4, currentDoc, slopeDimStruct.FamilySymbol.Name, out fs))
						{
							fs = null;
							return false;
						}
						transaction3.Commit();
						if (File.Exists(Ultility.GetUserTempDirectory() + text + ".rfa"))
						{
							Ultility.DeleteFile(Ultility.GetUserTempDirectory() + text + ".rfa");
						}
						return true;
					}
					catch (Exception)
					{
						if (File.Exists(Ultility.GetUserTempDirectory() + text + ".rfa"))
						{
							Ultility.DeleteFile(Ultility.GetUserTempDirectory() + text + ".rfa");
						}
						transaction3.RollBack();
						fs = null;
						return false;
					}
				}
			}
			if (File.Exists(Ultility.GetUserTempDirectory() + text + ".rfa"))
			{
				Ultility.DeleteFile(Ultility.GetUserTempDirectory() + text + ".rfa");
			}
			if (!SlopeDimesionOper.GetFamilySymbol(family4, currentDoc, slopeDimStruct.FamilySymbol.Name, out fs))
			{
				fs = null;
				return false;
			}
			return true;
		}

		private static bool GetFamilySymbol(Family family, Autodesk.Revit.DB.Document doc, string symbolName, out FamilySymbol fs)
		{
			foreach (ElementId elementId in family.GetFamilySymbolIds())
			{
				fs = (doc.GetElement(elementId) as FamilySymbol);
				if (fs != null && fs.Name.Contains(symbolName))
				{
					return true;
				}
			}
			fs = (doc.GetElement(family.GetFamilySymbolIds().First<ElementId>()) as FamilySymbol);
			return true;
		}

		public static bool CreateFamilySymbol1(Autodesk.Revit.DB.Document currentDoc, SlopeDimensionStruct slopeDimStruct, out FamilySymbol fs)
		{
			Family family = slopeDimStruct.Family;
			Document document = family.Document.EditFamily(family);
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(document);
			filteredElementCollector.OfClass(typeof(FamilySymbol)).OfCategory(BuiltInCategory.OST_GenericAnnotation);
			if (filteredElementCollector.Count<Element>() <= 0)
			{
				fs = null;
				return false;
			}
			string str = "";
			foreach (Element element in filteredElementCollector)
			{
				FamilySymbol familySymbol = element as FamilySymbol;
				if (familySymbol != null)
				{
					Family family2 = familySymbol.Family;
					Document document2 = family2.Document.EditFamily(family2);
					FilteredElementCollector filteredElementCollector2 = new FilteredElementCollector(document2);
					filteredElementCollector2.OfClass(typeof(TextElement));
					if (filteredElementCollector2.Count<Element>() <= 0)
					{
						fs = null;
						return false;
					}
					using (Transaction transaction = new Transaction(document2))
					{
						try
						{
							if ((int)transaction.Start("Create Family") != 1)
							{
								fs = null;
								return false;
							}
							foreach (Element element2 in filteredElementCollector2)
							{
								TextElement textElement = element2 as TextElement;
								if (textElement != null)
								{
									TextElementType symbol = textElement.Symbol;
									str = string.Concat(new object[]
									{
										slopeDimStruct.Font,
										"-",
										slopeDimStruct.TextHeight,
										"-",
										slopeDimStruct.TextWidth
									});
									symbol.get_Parameter(BuiltInParameter.TEXT_FONT).Set(slopeDimStruct.Font);
									symbol.get_Parameter(BuiltInParameter.TEXT_SIZE).Set(SlopeDimesionOper.MMToFeet(slopeDimStruct.TextHeight));
									symbol.get_Parameter(BuiltInParameter.TEXT_WIDTH_SCALE).Set(slopeDimStruct.TextWidth);
								}
							}
							transaction.Commit();
							if (!File.Exists(Ultility.GetUserTempDirectory() + str + ".rfa"))
							{
								document2.SaveAs(Ultility.GetUserTempDirectory() + str + ".rfa");
							}
							break;
						}
						catch (Exception)
						{
							transaction.RollBack();
							break;
						}
					}
				}
			}
			document.Close(false);
			Document document3 = family.Document.EditFamily(family);
			FamilySymbol familySymbol2 = null;
			using (Transaction transaction2 = new Transaction(document3))
			{
				try
				{
                    if ((int)transaction2.Start("Create Family") != 1)
					{
						fs = null;
						return false;
					}
					Family family3;
                    if (document3.LoadFamily(Ultility.GetUserTempDirectory() + str + ".rfa", out family3))
					{
						Ultility.DeleteFile(Ultility.GetUserTempDirectory() + str + ".rfa");
						familySymbol2 = (document3.GetElement(family3.GetFamilySymbolIds().First<ElementId>()) as FamilySymbol);
						Parameter parameter = familySymbol2.GetParameters("坡度值").First<Parameter>();
						try
						{
							FamilyParameter familyParameter = document3.FamilyManager.get_Parameter("排水坡度");
							if (familyParameter != null)
							{
								document3.FamilyManager.AssociateElementParameterToFamilyParameter(parameter, familyParameter);
							}
							else
							{
								FamilyParameter familyParameter2 = document3.FamilyManager.get_Parameter("坡度上");
								FamilyParameter familyParameter3 = document3.FamilyManager.get_Parameter("坡度下");
								document3.FamilyManager.AssociateElementParameterToFamilyParameter(parameter, familyParameter2);
								document3.FamilyManager.AssociateElementParameterToFamilyParameter(parameter, familyParameter3);
							}
						}
						catch (Exception)
						{
						}
					}
					transaction2.Commit();
				}
				catch (Exception)
				{
					transaction2.RollBack();
				}
			}
			string text = string.Concat(new object[]
			{
				family.Name,
				"-",
				slopeDimStruct.TextHeight,
				"-",
				slopeDimStruct.TextWidth
			});
			using (Transaction transaction3 = new Transaction(document3))
			{
				try
				{
                    if ((int)transaction3.Start("Create Family") != 1)
					{
						fs = null;
						return false;
					}
					FilteredElementCollector filteredElementCollector3 = new FilteredElementCollector(document3);
					filteredElementCollector3.OfClass(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_GenericAnnotation);
					foreach (Element element3 in filteredElementCollector3)
					{
						AnnotationSymbol annotationSymbol = element3 as AnnotationSymbol;
						if (annotationSymbol != null)
						{
							annotationSymbol.Symbol = familySymbol2;
							FamilyParameter familyParameter4 = document3.FamilyManager.get_Parameter("排水坡度");
						}
					}
					transaction3.Commit();
					if (!File.Exists(Ultility.GetUserTempDirectory() + text + ".rfa"))
					{
						document3.SaveAs(Ultility.GetUserTempDirectory() + text + ".rfa");
					}
				}
				catch (Exception)
				{
					Ultility.DeleteFile(Ultility.GetUserTempDirectory() + text + ".rfa");
					transaction3.RollBack();
				}
			}
			Family family4;
			if (!Ultility.IsExistFamily(currentDoc, text, out family4))
			{
				using (Transaction transaction4 = new Transaction(currentDoc))
				{
					try
					{
                        if ((int)transaction4.Start("LoadFamilySymbol") != 1)
						{
							fs = null;
							return false;
						}
                        currentDoc.LoadFamilySymbol(Ultility.GetUserTempDirectory() + text + ".rfa", slopeDimStruct.FamilySymbol.Name, out fs);
						Ultility.DeleteFile(Ultility.GetUserTempDirectory() + text + ".rfa");
						transaction4.Commit();
						return true;
					}
					catch (Exception)
					{
						Ultility.DeleteFile(Ultility.GetUserTempDirectory() + str + ".rfa");
						transaction4.RollBack();
						fs = null;
						return false;
					}
				}
			}
			Ultility.DeleteFile(Ultility.GetUserTempDirectory() + text + ".rfa");
			foreach (ElementId elementId in family4.GetFamilySymbolIds())
			{
				fs = (currentDoc.GetElement(elementId) as FamilySymbol);
				if (fs != null && fs.Name == slopeDimStruct.FamilySymbol.Name)
				{
					return true;
				}
			}
			fs = null;
			return false;
		}

		public static bool AddSlopeDimToDoc(SlopeDimensionData slopeDimData)
		{
			UIDocument activeUIDocument = slopeDimData.CommandData.Application.ActiveUIDocument;
			Document document = activeUIDocument.Document;
			Selection selection = activeUIDocument.Selection;
			XYZ startPoint = slopeDimData.StartPoint;
			XYZ endPoint = slopeDimData.EndPoint;
			bool flag = false;
			if (Geometry.LessThan(endPoint.X, startPoint.X))
			{
				flag = true;
			}
			XYZ xyz = endPoint - startPoint;
			Line line = Line.CreateUnbound(startPoint, document.ActiveView.ViewDirection);
			double num = document.ActiveView.RightDirection.AngleOnPlaneTo(xyz, document.ActiveView.ViewDirection);
			SlopeDimensionStruct slopeDimStruct = slopeDimData.SlopeDimStruct;
			FamilySymbol familySymbol;
			SlopeDimesionOper.CreateFamilySymbol(document, slopeDimStruct, out familySymbol);
			using (Transaction transaction = new Transaction(document))
			{
				try
				{
					if ((int)transaction.Start("Create SlopeDimension") != 1)
					{
						return false;
					}
					FamilyInstance familyInstance = document.Create.NewFamilyInstance(startPoint, familySymbol, document.ActiveView);
					document.Regenerate();
					familyInstance.GetParameters("坡度上").First<Parameter>().Set(slopeDimStruct.UpText);
					try
					{
						familyInstance.GetParameters("坡度下").First<Parameter>().Set(slopeDimStruct.DownText);
					}
					catch (Exception)
					{
					}
					familyInstance.GetParameters("箭头角度").First<Parameter>().Set(SlopeDimesionOper.AngleToRad(slopeDimStruct.ArrowAngle));
					familyInstance.GetParameters("箭头长度").First<Parameter>().Set(SlopeDimesionOper.MMToFeet(slopeDimStruct.ArrowLength));
					try
					{
						familyInstance.GetParameters("坡度值放置间距").First<Parameter>().Set(SlopeDimesionOper.MMToFeet(slopeDimStruct.Offset));
					}
					catch (Exception)
					{
						familyInstance.GetParameters("坡度值间距高度").First<Parameter>().Set(SlopeDimesionOper.MMToFeet(slopeDimStruct.Offset));
					}
					familyInstance.GetParameters("基线长度").First<Parameter>().Set(SlopeDimesionOper.MMToFeet(slopeDimStruct.Length));
					document.Regenerate();
					ElementTransformUtils.RotateElement(document, familyInstance.Id, line, num);
					if (flag)
					{
						Plane plane = RevitVersionFuncs.CreatePlanByOriginAndBasis(endPoint, (startPoint - endPoint).Normalize(), (endPoint.Add(document.ActiveView.ViewDirection * 100.0) - endPoint).Normalize());
						ElementTransformUtils.MirrorElement(document, familyInstance.Id, plane);
						document.Delete(familyInstance.Id);
					}
					transaction.Commit();
				}
				catch (Exception)
				{
					transaction.RollBack();
					return false;
				}
			}
			return true;
		}

		public static double RadToAngle(double rad)
		{
			return rad * 180.0 / Math.PI;
		}

		public static double FeetToMM(double feet)
		{
			return feet * 304.8;
		}

		public static double MMToFeet(double mm)
		{
			return mm / 304.8;
		}

		public static double AngleToRad(double angle)
		{
			return angle * Math.PI / 180.0;
		}

		public static double ReadTextMaxLenth(string name1, string name2)
		{
			int num = Encoding.Default.GetBytes(name1).Length;
			int num2 = Encoding.Default.GetBytes(name2).Length;
			if ((double)(num - num2) < 1E-08)
			{
				return (double)num2;
			}
			return (double)num;
		}

		public static bool AddSlopeDimToDoc(XYZ location, Autodesk.Revit.DB.Document doc, FamilySymbol familysymbol, out FamilyInstance fs)
		{
			using (Transaction transaction = new Transaction(doc))
			{
				try
				{
					if ((int)transaction.Start("Create SlopeDimension") != 1)
					{
						fs = null;
						return false;
					}
					fs = doc.Create.NewFamilyInstance(location, familysymbol, doc.ActiveView);
					transaction.Commit();
				}
				catch (Exception)
				{
					transaction.RollBack();
					fs = null;
					return false;
				}
			}
			return true;
		}

		public static bool ModifySlopeDimPara(Autodesk.Revit.DB.Document doc, FamilyInstance slopeDim, SlopeDimensionStruct slopeDimStruct)
		{
			using (Transaction transaction = new Transaction(doc))
			{
				try
				{
					if ((int)transaction.Start("Create SlopeDimension") != 1)
					{
						return false;
					}
					slopeDim.GetParameters("箭头角度").First<Parameter>().Set(25);
					slopeDim.GetParameters("箭头长度").First<Parameter>().Set(SlopeDimesionOper.MMToFeet(3.5));
					slopeDim.GetParameters("坡度值放置间距").First<Parameter>().Set(SlopeDimesionOper.MMToFeet(2.0));
					slopeDim.GetParameters("基线长度").First<Parameter>().Set(SlopeDimesionOper.MMToFeet(15.0));
					transaction.Commit();
				}
				catch (Exception)
				{
					transaction.RollBack();
					return false;
				}
			}
			return true;
		}

		public static bool RotateSlopeDim(Autodesk.Revit.DB.Document doc, double angel, Line axis, ElementId slopeDimId)
		{
			using (Transaction transaction = new Transaction(doc))
			{
				try
				{
					if ((int)transaction.Start("Create SlopeDimension") != 1)
					{
						return false;
					}
					ElementTransformUtils.RotateElement(doc, slopeDimId, axis, angel);
					transaction.Commit();
				}
				catch (Exception)
				{
					transaction.RollBack();
					return false;
				}
			}
			return true;
		}

		private const double preic = 1E-08;
	}
}
